package ar.com.quickMart.database.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import ar.com.quickMart.database.ListDao;
import ar.com.quickMart.database.PurchaseDao;
import ar.com.quickMart.database.quickMartDB;
import ar.com.quickMart.logic.Branch;
import ar.com.quickMart.logic.ConfirmedQuickMartList;
import ar.com.quickMart.logic.Product;
import ar.com.quickMart.logic.Promotion;
import ar.com.quickMart.logic.Purchasable;
import ar.com.quickMart.logic.SuperMarket;

public class PurchaseDaoMySql extends BaseDaoMySql implements PurchaseDao{
	
	/**
	 * 
	 * addPurchase
	 * 
	 * Registra una compra en la BDD.
	 * 	
	 * @param 	listId	Id de la lista que se compra
	 * @param 	date	Fecha en que se realiza la compra
	 * @return	true	En caso de exito
	 * 			false	En caso contrario
	 */
	public boolean addPurchase(int listId, Date date,float importeTotal) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO Compra (Fecha, Lista_id, EstadoDeCompra_id, ImporteTotal) VALUES (?, ?, 1,?);";
		// TODO esta hardcodeado el 1, porque hay que ver a que estado de compra pertenece una compra cuando se crea/agrega
	
		try {		
			// Creo la sentencia y ejecuto el query
			/*Statement statement = connection.createStatement();
			statement.executeUpdate(query);*/
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setTimestamp(1, new java.sql.Timestamp(date.getTime()));
			statement.setLong(2, listId);
			statement.setFloat(3, importeTotal);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar compra, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Compra agregada a lista, devuelvo true
		return true;
	}

	/**
	 * 
	 * getPurchaseId
	 * 
	 * Obtiene el id de una compra
	 * 
	 * @param 	listId	    Id de la lista asociada
	 * @param   userId      Id del usuario que tiene esa compra
	 * @return	Long		El Id de la compra
	 * 			
	 */
	
	public Long getPurchaseId(long listId){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		Long purchaseId;
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id " +
				" From Compra C " +
				" WHERE C.Lista_id = ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			if(result.next()) {
				purchaseId = result.getLong("id");
				
			}
			else {
				purchaseId = null;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
						
		// Desconecto de la BDD
		disconnect(connection);
		
		return purchaseId;
						
	}
	
	
	/**
	 * 
	 * removePurchase
	 * 
	 * Elimina una compra de la BDD.
	 * 
	 * @param 	purchaseId	Id de la compra a borrar
	 * @return	true		En caso de exito
	 * 			false		En caso contrario
	 */
	public boolean removePurchase(int purchaseId) {
		
		// TODO
		// Hay que borrar la lista asociada a la compra ?????????????????
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo los querys
		String query = "DELETE FROM Compra WHERE id = " + purchaseId;

		try {
			
			// Creo las sentencias y ejecuto ambas querys
			Statement statement = connection.createStatement();			
			statement.executeUpdate(query);
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al eliminar compra, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Compra eliminada, devuelvo true
		return true;
	}
	
	public ConfirmedQuickMartList getConfirmedQuickMartList(long listId){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		ConfirmedQuickMartList list;
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha, E.Descripcion, L.NombreLista " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" WHERE C.Lista_id = ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			if(result.next()) {
				list = new ConfirmedQuickMartList();
								
				list.setId(listId);
				list.setName(result.getString("NombreLista"));
				list.setState(result.getString("Descripcion"));
				list.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				list.setConfirmationDate(new Date(timeStamp.getTime()));
			}
			else {
				list = null;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
						
		// Desconecto de la BDD
		disconnect(connection);
						
		if(list== null){
			return null;
		}
		
		list.setUser(quickMartDB.getUserDao().getUserByListId(listId));
		
		if(list.getUser() == null){
			
			return null;
		}
		
		
		
		List<Product> products = quickMartDB.getListDao().getListProducts(list.getUser().getId(), list.getName());
		
		List<Promotion> promotions = quickMartDB.getListDao().getListPromotions(list.getUser().getId(), list.getName(), true);
		
		if(promotions != null){
			for(Promotion pr : promotions){
				
				products.addAll(pr.getProducts());
			}
		}
		
		
		
		if(products == null){
			
			return null;
		}
		else{
			list.setItems(new ArrayList<Purchasable>());
			list.getItems().addAll(products);
		}
		
		return list;	
	}
	
	public List<ConfirmedQuickMartList> getConfirmedQuickMartLists(String state){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" WHERE E.Descripcion = ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, state);
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			while(result.next()) {
				
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
								
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
				
				list.add(l);
			}
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
					
		// Desconecto de la BDD
		disconnect(connection);
						
		if(list.size() <= 0){
			return null;
		}
		
		for(ConfirmedQuickMartList l : list){
			
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
			
		}		
		
		return list;	
	}
	
	public List<ConfirmedQuickMartList> getConfirmedQuickMartListsByUser(String state, long userId){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista, S.Direccion As sucursal, SUP.nombre AS supermercado " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" JOIN Sucursal S ON L.Sucursal_id = S.id " +
				" JOIN Supermercado SUP ON S.Supermercado_id = SUP.id "+
				" WHERE E.Descripcion = ?" +
				" AND L.Usuario_id = ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, state);
			statement.setLong(2, userId);
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			while(result.next()) {
				
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
								
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
				
				l.setBranch(new Branch());
				l.getBranch().setSuperMarket(new SuperMarket());
				l.getBranch().setAddress(result.getString("sucursal"));
				l.getBranch().getSuperMarket().setName(result.getString("supermercado"));
				
				list.add(l);
			}
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
					
		// Desconecto de la BDD
		disconnect(connection);
						
		if(list.size() <= 0){
			return null;
		}
		
		for(ConfirmedQuickMartList l : list){
			
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
			
		}		
		
		return list;	
	}
	
	public List<ConfirmedQuickMartList> getConfirmedQuickMartListsByUser(String state, long userId, Date beginDate, Date endDate){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista, S.Direccion As sucursal, SUP.nombre AS supermercado " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" JOIN Sucursal S ON L.Sucursal_id = S.id " +
				" JOIN Supermercado SUP ON S.Supermercado_id = SUP.id "+
				" WHERE E.Descripcion = ?" +
				" AND L.Usuario_id = ?" +
				" AND C.Fecha >= ?" +
				" AND C.Fecha <= ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, state);
			statement.setLong(2, userId);
			statement.setDate(3, new java.sql.Date(beginDate.getTime()));
			statement.setDate(4, new java.sql.Date(endDate.getTime()));
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			while(result.next()) {
				
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
								
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
				
				l.setBranch(new Branch());
				l.getBranch().setSuperMarket(new SuperMarket());
				l.getBranch().setAddress(result.getString("sucursal"));
				l.getBranch().getSuperMarket().setName(result.getString("supermercado"));
				
				list.add(l);
			}
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
					
		// Desconecto de la BDD
		disconnect(connection);
						
		if(list.size() <= 0){
			return null;
		}
		
		for(ConfirmedQuickMartList l : list){
			
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
			
		}		
		
		return list;	
	}
	
	public List<ConfirmedQuickMartList> getConfirmedQuickMartLists(String state, int count){
		// Creo variable para la conexion
		Connection connection;
						
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" WHERE E.Descripcion = ?" +
				" ORDER BY C.Fecha LIMIT ?;";

		try {
							
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, state);
			statement.setInt(2, count);
			result = statement.executeQuery();
							
			// Obtengo datos de la consulta
			result = statement.getResultSet();
							
			while(result.next()) {
				
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
								
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
				
				list.add(l);
			}
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
							
			// Desconecto de la BDD
			disconnect(connection);
							
			// Error al obtener clave, devuelvo null
			return null;
		}
					
		// Desconecto de la BDD
		disconnect(connection);
						
		if(list.size() <= 0){
			return null;
		}
		
		for(ConfirmedQuickMartList l : list){
			
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
			
		}		
		
		return list;	
	}
	
	@Override
	public List<ConfirmedQuickMartList> getConfirmedQuickMartLists(
			String state, long branchId) {
		// Creo variable para la conexion
		Connection connection;
								
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
								
		// Abro la conexion
		connection = connect();
								
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" WHERE E.Descripcion = ?" +
				" AND L.Sucursal_id = ?;";

		try {
									
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			
			statement.setString(1, state);
			statement.setLong(2, branchId);
			
			result = statement.executeQuery();
									
			// Obtengo datos de la consulta
			result = statement.getResultSet();
									
			while(result.next()) {
						
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
										
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
						
				list.add(l);
			}
					
		}
		catch (Exception ex) {
			ex.printStackTrace();
									
			// Desconecto de la BDD
			disconnect(connection);
									
			// Error al obtener clave, devuelvo null
			return null;
		}
							
		// Desconecto de la BDD
		disconnect(connection);
								
		if(list.size() <= 0){
			return null;
		}
				
		for(ConfirmedQuickMartList l : list){
					
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
					
		}		
				
		return list;
	}

	@Override
	public List<ConfirmedQuickMartList> getConfirmedQuickMartLists(
			String state, long branchId, int count) {
		// Creo variable para la conexion
		Connection connection;
								
		// Creo variables para el resultado de la consulta
		ResultSet result;
		List<ConfirmedQuickMartList> list = new ArrayList<ConfirmedQuickMartList>();
								
		// Abro la conexion
		connection = connect();
								
		// Creo el query
		String query = "SELECT C.id, C.importeTotal, C.Fecha,  C.Lista_id, L.NombreLista " +
				" From Compra C " +
				" JOIN EstadoDECompra E ON C.EstadoDeCompra_id = E.id " +
				" JOIN Lista L ON L.idLista = C.Lista_id " +
				" WHERE E.Descripcion = ?" +
				" AND L.Sucursal_id = ? "+
				" ORDER BY C.Fecha LIMIT ?;";

		try {
									
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, state);
			statement.setLong(2, branchId);
			statement.setInt(3, count);
			
			
			result = statement.executeQuery();
									
			// Obtengo datos de la consulta
			result = statement.getResultSet();
									
			while(result.next()) {
						
				ConfirmedQuickMartList l = new ConfirmedQuickMartList();
										
				l.setId(result.getLong("Lista_id"));
				l.setName(result.getString("NombreLista"));
				l.setState(state);
				l.setTotalToPay(result.getFloat("importeTotal"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				l.setConfirmationDate(new Date(timeStamp.getTime()));
						
				list.add(l);
			}
					
		}
		catch (Exception ex) {
			ex.printStackTrace();
									
			// Desconecto de la BDD
			disconnect(connection);
									
			// Error al obtener clave, devuelvo null
			return null;
		}
							
		// Desconecto de la BDD
		disconnect(connection);
								
		if(list.size() <= 0){
			return null;
		}
				
		for(ConfirmedQuickMartList l : list){
					
			l.setUser(quickMartDB.getUserDao().getUserByListId(l.getId()));
			if(l.getUser() == null){
				return null;
			}
					
		}		
				
		return list;
	}

	
	/**
	 * 
	 * addPurchaseState
	 * 
	 * Agrega un estado de compra a la BDD.
	 * 
	 * @param 	description		Descripcion del estado de compra a agregar
	 * @return	true			En caso de exito
	 * 			false			En caso contrario
	 */
	public boolean addPurchaseState(String description) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO EstadoDeCompra (Descripcion) VALUES (\"" + description + "\")";

		try {		
			// Creo la sentencia y ejecuto el query
			Statement statement = connection.createStatement();
			statement.executeUpdate(query);
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar estado de compra, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Estado de compra agregado, devuelvo true
		return true;
	}
	
	/**
	 * 
	 * removePurchaseStateId
	 * 
	 * Elimina un estado de compra de la BDD.
	 * 
	 * @param 	purchaseStateId	Id del estado de compra a borrar
	 * @return	true			En caso de exito
	 * 			false			En caso contrario
	 */
	public boolean removePurchaseState(int purchaseStateId) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query
		String query = "DELETE FROM EstadoDeCompra WHERE id = " + purchaseStateId;

		try {
			
			// Creo la sentencia y ejecuto el query
			Statement statement = connection.createStatement();
			statement.executeUpdate(query);
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al eliminar estado de compra, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Estado de compra eliminado, devuelvo true
		return true;
	}
	
	public boolean updatePurchaseState(long listId, String newState){
		// Creo variable para la conexion
		Connection connection;
								
		int result;
		
		// Abro la conexion
		connection = connect();
								
		// Creo el query
		String query = "UPDATE Compra SET EstadoDeCompra_id = (SELECT E.id FROM EstadoDeCompra E WHERE E.Descripcion = ? ) WHERE Lista_id = ?; ";

				try {
									
					// Creo la sentencia y ejecuto el query
					PreparedStatement statement = connection.prepareStatement(query);
					statement.setString(1, newState);
					statement.setLong(2, listId);
					result = statement.executeUpdate();
									
					
				}
				catch (Exception ex) {
					ex.printStackTrace();
									
					// Desconecto de la BDD
					disconnect(connection);
									
					// Error al obtener clave, devuelvo null
					return false;
				}
							
				// Desconecto de la BDD
				disconnect(connection);
								
				if(result> 0){
					return true;
				}
				else{
					return false;
				}
	
	}

	@Override
	public boolean updatePurchaseDate(long listId, Date date) {
		// Creo variable para la conexion
		Connection connection;
								
		int result;
		
		// Abro la conexion
		connection = connect();
								
		// Creo el query
		String query = "UPDATE Compra SET fecha = ? WHERE Lista_id = ?; ";

				try {
									
					// Creo la sentencia y ejecuto el query
					PreparedStatement statement = connection.prepareStatement(query);
					statement.setTimestamp(1, new java.sql.Timestamp(date.getTime()));
					statement.setLong(2, listId);
					result = statement.executeUpdate();
									
					
				}
				catch (Exception ex) {
					ex.printStackTrace();
									
					// Desconecto de la BDD
					disconnect(connection);
									
					// Error al obtener clave, devuelvo null
					return false;
				}
							
				// Desconecto de la BDD
				disconnect(connection);
								
				if(result> 0){
					return true;
				}
				else{
					return false;
				}
	}


}
